﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Yuans.BinaryConfig
{
    public class ConfigItem
    {
        public enum ParamType
        {
            NUMBER_I8 = 0,
            NUMBER_U8,
            NUMBER_U16,
            NUMBER_I16,
            NUMBER_U32,
            NUMBER_I32,
            BOOL,
            STRING,
            BLOB,
            DATETIME,
        };

        public string ItemName{set;get;}
        public ParamType ItemType { set; get;}
        public int GetItemLengthByteNum()
        {
            if ((this.ItemType == ConfigItem.ParamType.STRING) || (this.ItemType == ConfigItem.ParamType.BLOB))
            {
                return 2;
            }
            else
            {
                return 1;
            }
        }
        public static int GetItemLengthByteNum(ConfigItem.ParamType itemType)
        {
            if ((itemType == ConfigItem.ParamType.STRING) || (itemType == ConfigItem.ParamType.BLOB))
            {
                return 2;
            }
            else
            {
                return 1;
            }
        }
        public byte[] GetItemRawBytes()
        {
            string itemName = this.ItemName;
            ConfigItem.ParamType itemType = this.ItemType;
            byte[] valueBytes = this.GetItemValueRawBytes();

            int nameStrLen = itemName.Length; // The terminator '\0' is not included.
            int valueLen = valueBytes.Length;

            int nameStrLenDescByteNum = 1; // 1 byte denotes the length of nameString
            int itemTypeDescByteNum = 1; // 1 byte denotes the item type
            int itemValueLenDescByteNum = GetItemLengthByteNum(); // ? byte denotes the byte num of value

            int itemBytesTotalLen = nameStrLenDescByteNum
                                    + nameStrLen
                                    + itemTypeDescByteNum
                                    + itemValueLenDescByteNum
                                    + valueLen;

            byte[] itemBytes = new byte[itemBytesTotalLen];

            itemBytes[0] = (byte)nameStrLen;

            Encoding.ASCII.GetBytes(itemName).CopyTo(itemBytes, nameStrLenDescByteNum);

            itemBytes[nameStrLenDescByteNum + nameStrLen] = (byte)itemType;

            if (itemValueLenDescByteNum > 1)
            {
                BitConverter.GetBytes((UInt16)valueLen).CopyTo(itemBytes, nameStrLenDescByteNum + nameStrLen + itemTypeDescByteNum);
            }
            else
            {
                itemBytes[nameStrLenDescByteNum + nameStrLen + itemTypeDescByteNum] = (byte)valueLen;
            }

            valueBytes.CopyTo(itemBytes, nameStrLenDescByteNum + nameStrLen + itemTypeDescByteNum + itemValueLenDescByteNum);

            return itemBytes;
        }
        public virtual string GetFriendValueDescription()
        {
            return ""; // Default empty string
        }
        public virtual byte[] GetItemValueRawBytes()
        {
            return null;
        }
    }
}
